home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir35 / cff51b.zip / PORTS / CFPORT.ZTC < prev    next >
Text File  |  1993-10-22  |  17KB  |  842 lines

  1. /* CFPORT.ZTC -- zortech c Version 3.0 dos extender model */
  2. /* PORTABILITY FOR CFF -- MODIFY TO SUIT THE COMPILER/OS IN USE */
  3.  
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <stdlib.h>
  7. #include <fcntl.h>
  8. #include <errno.h>
  9. #include <time.h>
  10. #include <io.h>
  11. #include <stdio.h>
  12. #include <direct.h>
  13. #include <dos.h>
  14. #include "..\cff.h"
  15.  
  16. extern void *mymemmove(void *, void *, long);
  17. extern int mystrlen(void *);
  18. extern int mystrcpy(void *, void *);
  19.  
  20. #define PCDOS 1
  21. #define HAS_NO_DIRENT 1
  22. #define HAS_NO_SYNC 1
  23. #define HAS_NO_FSYNC 1
  24.  
  25. #define NIBBLE 128
  26. #define CHUNK_SIZE 8192
  27.  
  28. #ifndef HEAPSTART
  29. #define HEAPSTART 0x50000
  30. #endif
  31.  
  32. unsigned long heapcreep;
  33. void *heapstart = (void *)HEAPSTART;
  34.  
  35.  
  36. static STOR BIGZERO;
  37.  
  38. /* DUMMY ROUTINES TO PREVENT LINKING UNWANTED MALLOC LIKE STUFF */
  39. int getpagesize(void)
  40. {
  41.     return 4096;
  42. }
  43. #if 0
  44. int _heapchk(void)
  45. {
  46.     return 0;
  47. }
  48.  
  49. int _heapset(unsigned a)
  50. {
  51.     return 0;
  52. }
  53. void *_expand (void *mem, size_t new_size)
  54. {
  55.     return NULL;
  56. }
  57. size_t _msize (const void *mem)
  58. {
  59.     return mallocsize(mem);
  60. }
  61. int _heapmin(void)
  62. {
  63.     return 0;
  64. }
  65. int _debug_heapmin(const char *fn, size_t ln)
  66. {
  67.     return 0;
  68. }
  69. void _debug_free( void *ptr, const char *fn, size_t ln)
  70. {
  71.     free(ptr);
  72. }
  73. void *_debug_calloc(size_t num, size_t size, const char *fn, size_t ln)
  74. {
  75.     return calloc(num, size);
  76. }
  77. void *_debug_malloc(size_t size, const char *fn, size_t ln)
  78. {
  79.     return malloc(size);
  80. }
  81. void *_debug_realloc(void *ptr, size_t size, const char *fn, size_t ln)
  82. {
  83.     return realloc(ptr, size);
  84. }
  85. void *_dump_allocated(int nbytes)
  86. {
  87.     return NULL;
  88. }
  89. void *_heap_check(void)
  90. {
  91.     return NULL;
  92. }
  93. #endif
  94. /* --------------- END OF MALLOC DUMMYS ------------------ */
  95.  
  96. static unsigned long
  97. round_up(long size, long amt)
  98. {
  99.     return (size&(amt-1)) ? size+(amt-(size&(amt-1))) : size;
  100. }
  101.  
  102.  
  103.  
  104. static int testflags = 0;
  105. void
  106. cfport_settestflags(int flags)
  107. {
  108.     testflags |= flags;
  109. }
  110. void
  111. cfport_clrtestflags(int flags)
  112. {
  113.     testflags &= ~flags;
  114. }
  115.  
  116. static void
  117. fix_statbuf(struct stat *stat, CFSTAT *sbuf)
  118. {
  119.     sbuf->st_atime = stat->st_atime;
  120.     sbuf->st_mtime = stat->st_mtime;
  121.     sbuf->st_ctime = stat->st_ctime;
  122.     sbuf->st_size = stat->st_size;
  123.     sbuf->st_alloc = stat->st_size;
  124.     sbuf->st_filesize = stat->st_size;
  125.     sbuf->st_filealloc = stat->st_size;
  126. #if 0
  127.     sbuf->st_blksize = stat->st_blksize;
  128. #else
  129.     sbuf->st_blksize = 8192;
  130. #endif
  131.     sbuf->st_dev = stat->st_dev;
  132.     sbuf->st_ino = stat->st_ino;
  133.     sbuf->st_nlink = stat->st_nlink;
  134.     sbuf->st_uid = stat->st_uid;
  135.     sbuf->st_gid = stat->st_gid;    
  136.     sbuf->st_rdev = stat->st_rdev;
  137.     sbuf->st_mode = stat->st_mode;
  138. }
  139.  
  140. void *
  141. PORTSBRK(unsigned long amt)
  142. {
  143.     return sbrk(amt);
  144. }
  145. void
  146. PORTHEAPSTART(void)
  147. {
  148. void *curstart = sbrk(0);
  149. char *newstart = NULL;
  150.  
  151.     if(curstart > heapstart)
  152.     {
  153.         cfprintf("CFPORT: The heap safety zone was exceeded by %d bytes.\n",
  154.         -((long)((unsigned long)heapstart - (unsigned long)curstart)));
  155.         cfprintf("        Modify 'heapstart' in cfport.c\n");
  156. #if HAS_NO_SBRK == 1
  157.         cfprintf("        sbrkmem_base=%0xlx=%lu sbrk_alloc=%lu\n",
  158.         sbrkmem_base, mem_alloced);
  159. #endif
  160.         exit(-1);
  161.     }
  162.     heapcreep = (unsigned long)((unsigned long)heapstart - (unsigned long)curstart);
  163.     if((newstart = sbrk(heapcreep)) == (void *)-1) {
  164.         cfprintf("Failed to set heap: zone=%lu HEAPSTART=%p curstart=%p.\n",
  165.         heapcreep, heapstart, curstart);
  166.         exit(-2);
  167.     }
  168.     else if(heapcreep && newstart+heapcreep != heapstart) {
  169.         cfprintf("Heap was not set properly: desired=%p result=%p zone=%lu.\n",
  170.         heapstart, newstart, heapcreep);
  171.         exit(-3);
  172.     }
  173. }
  174. int
  175. PORTSTAT(void *path, CFSTAT *sbuf)
  176. {
  177. struct stat _stat;
  178. int result = stat(path, &_stat);
  179.     if(result == 0)
  180.         fix_statbuf(&_stat, sbuf);
  181.     return result;
  182. }
  183. void
  184. PORTFSTAT(int handle, CFSTAT *sbuf)
  185. {
  186. struct stat _stat;
  187.  
  188.     fstat(handle, &_stat);
  189.     fix_statbuf(&_stat, sbuf);    
  190. }
  191.  
  192. long
  193. PORTREAD(long handle, void *mem_addr, STOR dsk_addr, long amount)
  194. {
  195.     lseek(handle, dsk_addr.a0, SEEK_SET);  
  196.     return read(handle, mem_addr, amount);
  197.  
  198. }
  199. long
  200. PORTWRITE(long handle, void *mem_addr, STOR dsk_addr, long amount)
  201. {
  202.     lseek(handle, dsk_addr.a0, SEEK_SET);  
  203.     return write(handle, mem_addr, amount);
  204. }
  205. void
  206. PORTSEEK(long handle, STOR spot, int mode, STOR *loc)
  207. {
  208. STOR ret;
  209.     switch(mode)
  210.     {
  211.         case S_END:
  212.             mode = SEEK_END;
  213.             break;
  214.         case S_CUR:
  215.             mode = SEEK_CUR;
  216.             break;
  217.         case S_SET:
  218.             mode = SEEK_SET;
  219.             break;
  220.         default:
  221.             mode = -1;
  222.     }
  223.     ret.a4.s1 = 0;
  224.     ret.a4.s0 = lseek((int)handle, spot.a0, mode);
  225.     if(loc)
  226.         *loc = ret;
  227. }
  228. long
  229. PORTOPEN(void *path, int mode)
  230. {
  231. int omode = O_BINARY;
  232.  
  233.     if(mode & F_STAT)
  234.         omode |= O_RDONLY;
  235.     else if((mode & F_RDWR) == F_RDWR)
  236.         omode |= O_RDWR;
  237.     else if((mode & F_RDWR) == F_WRONLY)
  238.         omode |= O_RDWR;
  239.     else if((mode & F_RDWR) == F_RDONLY)
  240.         omode |= O_RDONLY;
  241.     if(mode & F_TRUNC)
  242.         omode |= O_TRUNC;
  243.     if(mode & F_EXCL)
  244.         omode |= O_EXCL;
  245.     if(mode & F_APPEND)
  246.         omode |= O_APPEND;
  247.  
  248.     return open(path,omode);
  249. }
  250. long
  251. PORTCLOSE(long handle)
  252. {
  253.     return close((int)handle);
  254. }
  255. long
  256. PORTCREATE(void *path, int mode)
  257. {
  258.     return open(path,O_BINARY|O_CREAT|O_TRUNC|O_RDWR,S_IREAD|S_IWRITE);
  259. }
  260. long
  261. PORTUNLINK(void *path)
  262. {
  263.     return unlink(path);
  264. }
  265.  
  266. #if PCDOS == 1
  267. static void
  268. dos_truncate(short handle, long amount)
  269. {
  270. #include <dos.h>
  271. union REGS r;
  272.  
  273.     r.h.al = 0;        /* SEEK_SET */
  274.     r.h.ah = 0x42;    /* seek */
  275.     r.x.bx = handle;
  276.     r.x.dx = (short)amount;
  277.     r.x.cx = (short)(amount>>16);
  278.     int86(0x21,&r,&r);
  279.  
  280.     r.h.ah = 0x40;    /* write */
  281.     r.x.bx = handle;
  282.     r.x.cx = 0;        /* amount == 0 */
  283.     int86(0x21,&r,&r);
  284.     
  285.     r.h.ah = 0x3e;    /* close */
  286.     r.x.bx = handle;
  287.     int86(0x21,&r,&r);
  288. }
  289. #endif
  290. #if HAS_NO_FTRUNCATE == 1
  291. static int
  292. ftruncate(int handle, long size)
  293. {
  294. }
  295. #endif
  296. #if HAS_NO_FSYNC == 1
  297. static int
  298. fsync(int handle)
  299. {
  300. }
  301. #endif
  302. #if HAS_NO_SYNC == 1
  303. static void
  304. sync(void)
  305. {
  306. }
  307. #endif
  308.  
  309. long
  310. PORTTRUNCATE(long handle, char *path, STOR amount)
  311. {
  312. #if PCDOS == 1
  313.     dos_truncate((short)handle, amount.a0);
  314.     return PORTOPEN(path, F_RDWR);
  315.  
  316. #else
  317.     ftruncate((int)handle, amount.a0);
  318.     return handle;
  319. #endif
  320. }
  321. void
  322. PORTCLOSETRUNC(long handle, STOR amount)
  323. {
  324. #if PCDOS == 1
  325.     dos_truncate((short)handle, amount.a0);
  326. #else
  327.     ftruncate((int)handle, amount.a0);
  328.     close((int)handle);
  329. #endif
  330. }
  331.  
  332. void
  333. PORTFLUSH(long handle)
  334. {
  335.     if(handle < 0)
  336.          sync();
  337.     else fsync((int)handle);
  338. }
  339.  
  340. char *
  341. PORTGETCWD(void *buf, int maxlen)
  342. {
  343. char *result;
  344.  
  345.     result = getcwd((char *)buf, maxlen);
  346.     ((char *)buf)[maxlen] = 0;
  347.     if(result)
  348.     {
  349.     char *cp = (char *)buf;
  350.         while(*cp != 0)
  351.         {
  352.             if(*cp == '\\') *cp = '/';
  353.             ++cp;
  354.         }
  355.     }
  356.     return result;
  357. }
  358.  
  359. long
  360. PORTCHDIR(void *path)
  361. {
  362.     return chdir(path);
  363. }
  364. unsigned long
  365. PORTTIME(void)
  366. {
  367.     return time(NULL);
  368. }
  369. unsigned long
  370. PORTCLOCK(void)
  371. {
  372.     return clock();
  373. }
  374. void
  375. PORTABORT(void)
  376. {
  377.  
  378.     abort();
  379. }
  380.  
  381. /* THE BASIC OS DRIVERS */
  382.  
  383. /* Primary Memory driver */
  384. long
  385. pmem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  386. {
  387.     switch(func)
  388.     {
  389.         case    S_GETSPACE:
  390.         {
  391.         unsigned long min, nib, current;
  392.  
  393.             amount = round_up(amount, CHUNK_SIZE);
  394.             min = round_up(amount / 4, CHUNK_SIZE);
  395.             nib = round_up(amount / 16, CHUNK_SIZE);
  396.             current = amount;
  397.             ((STOR *)mem_addr)->a2.size = 0;
  398.             ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  399.  
  400.             while(current >= min) {
  401.               if((((STOR *)mem_addr)->a1 = PORTSBRK(current)) != (void *)-1) {
  402.                 if(((STOR *)mem_addr)->a0 & (NIBBLE-1))
  403.                 {/* Normally the system uses NIBBLE bytes as the alignment */
  404.                   ((STOR *)mem_addr)->a0 = 
  405.                               round_up(((STOR *)mem_addr)->a0, NIBBLE);
  406.                   current -= NIBBLE;
  407.                 }
  408.                 ((STOR *)mem_addr)->a2.size = current;
  409.                 return 0;
  410.               }
  411.               current -= nib;
  412.             }
  413.             return 1;
  414.         }
  415.         case    S_GIVESPACE:
  416.             return 1;
  417.         default:
  418.             return 1;
  419.     }
  420.     return 0;
  421. }
  422.  
  423. /* Secondary Memory driver */
  424. long
  425. smem_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  426. {
  427.     if(!(testflags & 1))
  428.     {/* 
  429.         IF SECONDARY MEMORY REALLY EXISTS, THEN PUT A REAL DRIVER HERE.
  430.         The system adapts to a 0 return from S_GETSPACE by mapping 
  431.         secondary memory to primary memory when cfinit is called.
  432.         S_OPEN is never called.
  433.      */
  434.         switch (func)
  435.         {
  436.             case S_GETSPACE:
  437.                 *((long *)mem_addr) = 0;
  438.                 break;
  439.         }
  440.         return -1;
  441.     } /* END: Real driver */
  442.     else {
  443.     /* THIS CODE IS JUST FOR TESTING PURPOSES, IT USES A LOCAL MEMORY BUFFER */
  444.  
  445. #define SMEMMAX (4096*1024)
  446. static char *sbuf = NULL;
  447. static long smemalloc = 0;
  448.  
  449.         if(sbuf == NULL) {
  450.             if((sbuf = PORTSBRK(SMEMMAX)) == (void *)-1) {
  451.                 cfprintf("SMEM_DRIVER: Failed to init test memory block.\n");
  452.                 exit(-1);
  453.             }
  454.         }
  455.         switch(func)
  456.         {
  457.             case    S_CLOSE:
  458.                 return 0;        /* a real driver would do something */            
  459.             case    S_READBLK:
  460.             case    S_WRITEBLK:
  461.             {
  462.             char *smemaddr = sbuf + dsk_addr.a0;
  463.             long xfer = amount;
  464.                 if(dsk_addr.a0 + amount > smemalloc)
  465.                     xfer = smemalloc - dsk_addr.a0;
  466.                 if(xfer < 0) {
  467.                     return -1;
  468.                 }
  469.                 if(func == S_READBLK)
  470.                      mymemmove(mem_addr, smemaddr, xfer);
  471.                 else mymemmove(smemaddr, mem_addr, xfer);
  472.                 return xfer;
  473.             }
  474.             case    S_GETSPACE:
  475.                 amount = round_up(amount, CHUNK_SIZE);
  476.                 ((STOR *)mem_addr)->a0 = smemalloc;
  477.                 ((STOR *)mem_addr)->a2.size = 0;
  478.                 ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  479.                 if(amount + smemalloc < SMEMMAX) {
  480.                     ((STOR *)mem_addr)->a2.size = amount;
  481.                     smemalloc += amount;
  482.                     return 0;
  483.                 } else {/* Not enough space available, return error + avail */
  484.                     ((STOR *)mem_addr)->a2.size = 
  485.                                     (SMEMMAX - smemalloc) & ~CHUNK_SIZE;
  486.                     return 1;
  487.                 }
  488.             case    S_GIVESPACE:
  489. #if 0
  490. cfprintf("SMEM: GIVESPACE at loc=%lx size=%lu curbase=%lx\n",
  491. ((STOR *)mem_addr)->a0, ((STOR *)mem_addr)->a2.size, smemalloc);
  492. #endif
  493.                 if(((STOR *)mem_addr)->a0 == 
  494.                         smemalloc - ((STOR *)mem_addr)->a2.size)
  495.                 {/* Accept returns if they are at the end */
  496.                     smemalloc -= ((STOR *)mem_addr)->a2.size;
  497. #if 0
  498. cfprintf("SMEM: Truncate to %lu bytes\n", smemalloc);
  499. #endif
  500.                     return 0;
  501.                 }
  502.                 break;
  503.             default:
  504.                 break;
  505.         }
  506.         return 1;
  507.     }/* END: test driver */
  508. }
  509.  
  510. /* Internal file driver */
  511. long
  512. cfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  513. {
  514. long result = 0;
  515.  
  516.     switch(func)
  517.     {
  518.         case S_READBLK:
  519.             result = PORTREAD(handle, mem_addr, dsk_addr, amount);
  520.             break;
  521.         case S_WRITEBLK:
  522.             result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
  523.             break;
  524.         case    S_GETSPACE:
  525.         {
  526.         unsigned long result;
  527.         STOR base;
  528.         STOR end;
  529.             PORTSEEK(handle, BIGZERO, S_END, &base);
  530.             amount = round_up(amount, CHUNK_SIZE);
  531.             end.a4.s0 = base.a0 + amount-1;
  532.             end.a4.s1 = 0;
  533.             PORTWRITE(handle, "0", end, 1);
  534.             PORTSEEK(handle, BIGZERO, S_END, &end);
  535.             result = end.a0 - base.a0;
  536.             ((STOR *)mem_addr)->a0 = base.a0;
  537.             ((STOR *)mem_addr)->a2.size = result;
  538.             ((STOR *)mem_addr)->a2.type = STO_CHUNK;
  539.             return (result == amount) ? 0:1;        
  540.         }
  541.         case    S_GIVESPACE:
  542.         {
  543.         STOR base; 
  544.             PORTSEEK(handle, BIGZERO, S_END, &base);
  545.             if((((STOR *)mem_addr)->a0 + ((STOR *)mem_addr)->a2.size) == base.a0)
  546.             {/* OK to return space if at end */
  547. #if 0
  548.             long result;
  549.                 base.a0 -= ((STOR *)mem_addr)->a2.size;
  550.                 result = PORTTRUNCATE(handle, base);
  551. #endif
  552.                 return 0;
  553.             }
  554.             else return 1;
  555.         }
  556.         case    S_OPEN:
  557.             result = PORTOPEN(mem_addr, handle);
  558.             break;
  559.         case    S_CLOSE:
  560.             result = PORTCLOSE(handle);
  561.             break;
  562.         case    S_CREATE:
  563.             result = PORTCREATE(mem_addr, handle);
  564.             break;
  565.         case    S_UNLINK:
  566.             result = PORTUNLINK(mem_addr);
  567.             break;
  568.         case    S_SEEK:
  569.             PORTSEEK(handle, dsk_addr, amount, mem_addr);
  570.             break;
  571.         case    S_FLUSH:
  572.             PORTFLUSH(handle);
  573.             break;
  574.         case    S_CLOSETRUNC: /* truncate and close, (PCDOS needs this) */
  575.             PORTCLOSETRUNC(handle, dsk_addr);
  576.             break;
  577.         default:
  578.             return 1;
  579.     }
  580.     return result;
  581. }
  582. /* External file driver */
  583. long
  584. xfile_driver(int func, int handle, void *mem_addr, STOR dsk_addr, long amount)
  585. {
  586. long result = 0;
  587.  
  588.     switch(func)
  589.     {
  590.         case    S_GETSPACE:
  591.             ((STOR *)mem_addr)->a2.size = 0;
  592.         case    S_GIVESPACE:
  593.             return 1;
  594.         case    S_OPEN:
  595.             result = PORTOPEN(mem_addr, handle);
  596.             break;
  597.         case    S_CLOSE:
  598.             result = PORTCLOSE(handle);
  599.             break;
  600.         case    S_UNLINK:
  601.             result = PORTUNLINK(mem_addr);
  602.             break;
  603.         case    S_CREATE:
  604.             result = PORTCREATE(mem_addr,handle);
  605.             break;
  606.         case    S_READBLK:
  607.             result = PORTREAD(handle, mem_addr, dsk_addr, amount);
  608.             break;
  609.         case    S_WRITEBLK:
  610.             result = PORTWRITE(handle, mem_addr, dsk_addr, amount);
  611.             break;
  612.         case    S_SEEK:
  613.             PORTSEEK(handle, dsk_addr, amount, mem_addr);
  614.             break;
  615.         case    S_FLUSH:
  616.             PORTFLUSH(handle);
  617.             break;
  618.         default:
  619.             return 1;
  620.     }
  621.     return result;
  622. }
  623. #if HAS_NO_DIRENT == 1
  624. struct dirent {
  625.     int d_namlen;
  626.     char *d_name;
  627. };
  628. typedef struct {
  629.     unsigned long id;
  630.     long cur_spot;
  631.     char *path;
  632.     struct dirent d;
  633. } DIR;
  634. #define DIRP_ID (0x82018373)
  635.  
  636. static void *
  637. opendir(void *path)
  638. {
  639. DIR *dirp;
  640. unsigned long search_count = 1;
  641. struct FIND *result = NULL;
  642.  
  643.     if(!path)
  644.         return NULL;
  645.  
  646.     if((dirp = calloc(1,sizeof(DIR))) != NULL)
  647.     {
  648.         dirp->id = DIRP_ID;
  649.         if((dirp->path = malloc(mystrlen(path)+20)) != NULL)
  650.         {
  651.         int x = mystrcpy(dirp->path, path);
  652.             mystrcpy(&dirp->path[x], "\\*.*");
  653.             result = findfirst(dirp->path,0);                            
  654.             if(!result)
  655.             {
  656.                 free(dirp->path);
  657.             }
  658.         }
  659.         if(!result)
  660.         {
  661.             free(dirp);
  662.             dirp = NULL;
  663.         }
  664.     }
  665.     return dirp;
  666. }
  667. static void *
  668. readdir(DIR *dirp)
  669. {
  670. struct FIND *result;
  671.  
  672.     if(!dirp || dirp->id != DIRP_ID)
  673.         return NULL;
  674.  
  675.     if(dirp->cur_spot == 0)
  676.     {
  677.         result = findfirst(dirp->path,0);                                
  678.     }
  679.     else if(dirp->cur_spot > 0)
  680.     {
  681.         result = findnext();
  682.     }
  683.     if(result)
  684.     {
  685.         dirp->cur_spot += 1;
  686.         dirp->d.d_namlen = mystrlen(result->name);
  687.         dirp->d.d_name = result->name;
  688.         return &dirp->d;
  689.     }
  690.     else
  691.         dirp->cur_spot = -1;
  692.  
  693.     return NULL;
  694. }
  695. static long
  696. telldir(DIR *dirp)
  697. {
  698.     if(!dirp || dirp->id != DIRP_ID)
  699.         return -1;
  700.     return dirp->cur_spot;
  701. }
  702. static void
  703. seekdir(DIR *dirp, long spot)
  704. {
  705.     if(dirp && dirp->id == DIRP_ID && spot >= 0)
  706.     {
  707.     long i;
  708.         dirp->cur_spot = 0;
  709.         for(i = 0; i < spot; ++i)
  710.             if(!readdir(dirp))
  711.                 break;
  712.     }
  713. }
  714. static void
  715. rewinddir(DIR *dirp)
  716. {
  717.     if(dirp && dirp->id == DIRP_ID)
  718.     {
  719.         dirp->cur_spot = 0;
  720.     }
  721. }
  722. static void
  723. closedir(DIR *dirp)
  724. {
  725.     if(dirp && dirp->id == DIRP_ID)
  726.     {
  727.         free(dirp->path);
  728.         free(dirp);
  729.     }
  730. }
  731. #else
  732. #include <dirent.h>
  733. #endif
  734.  
  735. void *
  736. PORTOPENDIR(char *name)
  737. {
  738.     return opendir(name);
  739. }
  740. void *
  741. PORTREADDIR(void *it, CFDIRENT *d)
  742. {
  743. struct dirent *rd;
  744.     if((rd = readdir((DIR *)it)) != NULL) {
  745.         d->d_namlen = rd->d_namlen;
  746.         d->d_name = rd->d_name;
  747.         d->d_mode = M_EXTRNFILE;
  748.     }
  749.     return rd;
  750. }
  751. void
  752. PORTTELLDIR(void *it, STOR *loc)
  753. {
  754. STOR me;
  755.     me.a4.s0 = 0;
  756.     me.a4.s1 = 0;
  757.     me.a0 = telldir((DIR *)it); 
  758.     if(loc)
  759.         *loc = me;
  760. }
  761. void
  762. PORTSEEKDIR(void *it, STOR *loc)
  763. {
  764.     seekdir((DIR *)it, loc->a0);
  765. }
  766. void
  767. PORTREWINDDIR(void *it)
  768. {
  769.     rewinddir((DIR *)it);
  770. }
  771. void
  772. PORTCLOSEDIR(void *it)
  773. {
  774.     closedir((DIR *)it);
  775. }
  776. int
  777. PORTPRINT(int c)
  778. {
  779.     return write(1, &c, 1);
  780. }
  781.  
  782. #if 0
  783. /* 
  784.     THIS CODE IS FOR SAMPLE PURPOSES ONLY -- THE REAL CODE IS IN THE LIBRARY
  785.     PROGRAMMERS WHO WISH TO CREATE CUSTOM COMPARISON ROUTINES CAN USE THESE
  786.     FUNCTIONS AS MODELS.
  787. */
  788. /*
  789.     default_keycmp - system key comparison
  790.  
  791.     Return:    LESS    if keya <  keyb
  792.             EQUAL    if keya == keyb
  793.             GREATER    if keya >  keyb
  794. */
  795. static __inline__ int
  796. mymemcmp(unsigned char *a, unsigned char *b, int len)
  797. {
  798. int result = 0;
  799.     do {
  800.         if((result = ((int)*a++) - ((int)*b++)))
  801.             return result;
  802.     } while(--len);
  803.     return result;
  804. }
  805. int
  806. default_keycmp (void *keya, int    lena, void *keyb, int lenb)
  807. {
  808. int    result;
  809.  
  810.     if (lena == 0)
  811.         return ( (lenb == 0) ? EQUAL : LESS );
  812.     else if (lenb == 0)
  813.         return (GREATER);
  814.  
  815.  
  816.     result = mymemcmp (keya, keyb, ((lena<lenb)?lena:lenb));
  817.  
  818.     if (result < 0)
  819.         return LESS;
  820.     if (result > 0)
  821.         return GREATER;
  822.  
  823.     return ((lena == lenb) ? EQUAL : ((lena < lenb) ? LESS : GREATER));
  824.  
  825. }
  826. /*
  827.     default_itemcmp - system item comparison
  828.  
  829.     Return:    LESS-1        if itema <  itemb
  830.             EQUAL+1        if itema == itemb
  831.             GREATER+1    if itema >  itemb
  832. */
  833.  
  834. int
  835. default_itemcmp (Item *a, Item *b)
  836. {
  837.     return ( (a->item == b->item) ? 
  838.                 EQUAL+1 : ((a->item < b->item) ? LESS-1 : GREATER+1) );
  839. }
  840.  
  841. #endif
  842.